﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PortalCurriculo.Util.PasswordComplexity;

namespace PortalCurriculo.Util.Security
{
   /// <summary>
   /// Interface for defining a password policy
   /// </summary>
   /// <remarks>
   /// This security policy determines whether passwords meet pre-determined complexity requirements.
   /// 
   /// If this policy is enabled, passwords must meet the following minimum requirements:
   /// 
   /// Not contain the user's account name or parts of the user's full name that exceed two consecutive characters
   /// Be at least <see cref="MinimumPasswordLength"/> characters in length
   /// Contain characters from three of the following four categories:
   /// English uppercase characters (A through Z)
   /// English lowercase characters (a through z)
   /// Base 10 digits (0 through 9)
   /// Non-alphabetic characters (for example, !, $, #, %)
   /// 
   /// Complexity requirements are enforced when passwords are changed or created.
   /// </remarks>
   public interface IPasswordPolicy : IPolicy
   {

      /// <summary>
      /// Indicates the minimum password strength index for this policy (see <see cref="PasswordStrengthIndex"/>)
      /// </summary>
      /// <value>The minimum index of the password strength.</value>
      PasswordStrengthIndex MinimumPasswordStrengthIndex
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets the minimum length of the password.
      /// </summary>
      /// <value>The minimum length of the password.</value>
      int MinimumPasswordLength
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets the maximum length of the password.
      /// </summary>
      /// <value>The maximum length of the password.</value>
      int MaximumPasswordLength
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets a value indicating whether [require mixed case].
      /// </summary>
      /// <value><c>true</c> if [require mixed case]; otherwise, <c>false</c>.</value>
      bool RequireMixedCase
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets a value indicating whether [require digits].
      /// </summary>
      /// <value><c>true</c> if [require digits]; otherwise, <c>false</c>.</value>
      bool RequireDigits
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets a value indicating whether [require special characters].
      /// </summary>
      /// <value>
      /// 	<c>true</c> if [require special characters]; otherwise, <c>false</c>.
      /// </value>
      bool RequireSpecialCharacters
      {
         get;
         set;
      }

      /// <summary>
      /// Indicates if the username needs to be additionally supplied to verify the password complexity against
      /// </summary>
      /// <value>
      /// 	<c>true</c> if [require username to check password against]; otherwise, <c>false</c>.
      /// </value>
      bool RequireUserNameToCheckPasswordAgainst
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets the maximum count of characters in a sequence
      /// </summary>
      /// <value>The maximum count of characters in a sequence.</value>
      int MaximumCharacterSequenceCount
      {
         get;
         set;
      }

      /// <summary>
      /// Time in minutes the password is allows to be used for after issue/change
      /// </summary>
      /// <remarks>
      /// Used to restrict the life of the password.
      /// </remarks>
      /// <value>The password expiry in minutes.</value>
      int PasswordExpiryInMinutes
      {
         get;
         set;
      }

      /// <summary>
      /// Determines how quickly a password can be changed after it was changed.
      /// </summary>
      /// <remarks>
      /// This is a security measure to avoid allowing users from changing their password in
      /// a way to avoid 'gaming' the system. For example if the policy is setup to check
      /// the last 10 passwords, if the user is forced to change their password they could
      /// change it 11 times to get back to their old password. This way they are weakening
      /// their own password because although it has technically changed it is using the
      /// same password 99.9% of the time.
      /// </remarks>
      /// <value>The cannot change password after change until.</value>
      int MinutesBeforeUserCanChangePasswordAgain
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets the number of old passwords to check 
      /// </summary>
      /// <value>The maximum count of characters in a sequence.</value>
      int PasswordHistoryCountToCheck
      {
         get;
         set;
      }

      /// <summary>
      /// The duration of the lockout in minutes.
      /// </summary>
      /// <remarks>
      /// This security setting determines the number of minutes a locked-out account 
      /// remains locked out before automatically becoming unlocked. The available 
      /// range is from 0 minutes through 99,999 minutes. If you set the account 
      /// lockout duration to less than zero, the account will be locked out until an
      /// administrator explicitly unlocks it. If an account lockout threshold is 
      /// defined, the account lockout duration must be greater than or equal to 
      /// the reset time.
      /// </remarks>
      /// <value>The duration of the lockout.</value>
      int LockoutDuration
      {
         get;
         set;
      }

      /// <summary>
      /// Gets or sets the lockout threshold.
      /// </summary>
      /// <remarks>
      /// This security setting determines the number of failed logon attempts that 
      /// causes a user account to be locked out. A locked-out account cannot be 
      /// used until it is reset by an administrator or until the lockout duration 
      /// for the account has expired. You can set a value between 0 and 999 failed 
      /// logon attempts. If you set the value to 0, the account will never be locked out.
      /// </remarks>
      /// <value>The lockout threshold.</value>
      int LockoutThreshold
      {
         get;
         set;
      }

      /// <summary>
      /// Reset account lockout after X minutes
      /// </summary>
      /// <remarks>
      /// This security setting determines the number of minutes that must 
      /// elapse after a failed logon attempt before the failed logon attempt 
      /// counter is reset to 0 bad logon attempts. The available range is 
      /// 1 minute to 99,999 minutes.
      /// </remarks>
      /// <value>The duration of the lockout.</value>
      int LockoutResetInMinutes
      {
         get;
         set;
      }

      /// <summary>
      /// Resets to defined policy strength.
      /// </summary>
      /// <remarks>
      /// Used to set the policy to a predetermined strength. Note since this is destructive
      /// all the <see cref="Name"/>, <see cref="Identifier"/>, <see cref="Description"/> are
      /// also reset to known values
      /// </remarks>
      /// <param name="strength">The strength.</param>
      void ResetToDefinedPolicyStrength(PasswordStrengthIndex strength);

   }
}
